/*
Copyright 2017 yangchong211（github.com/yangchong211）

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package com.yc.video.tool;

import ohos.aafwk.ability.Ability;
import ohos.aafwk.ability.Lifecycle;
import ohos.agp.components.AttrHelper;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.StackLayout;
import ohos.agp.utils.Point;
import ohos.agp.window.service.Display;
import ohos.agp.window.service.DisplayManager;
import ohos.agp.window.service.WindowManager;
import ohos.app.Context;
import ohos.data.DatabaseHelper;
import ohos.data.preferences.Preferences;
import ohos.global.configuration.Configuration;
import ohos.multimodalinput.event.TouchEvent;
import ohos.net.NetHandle;
import ohos.net.NetManager;

import com.yc.kernel.utils.VideoLogUtils;
import com.yc.video.config.ConstantKeys;
import com.yc.video.config.VideoPlayerConfig;
import com.yc.video.player.VideoViewManager;

import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Formatter;
import java.util.List;
import java.util.Locale;

/**
 * 工具类
 *
 * @since 2021-05-10
 */
public final class PlayerUtils {
    private static final int COUNT_10 = 10;
    private static final int COUNT_60 = 60;
    private static final int COUNT_1000 = 1000;
    private static final int COUNT_3600 = 3600;
    private static final String STRING_0 = "0";
    private static final String STRING_M = ":";

    /**
     * 通过上下文获取到activity，使用到了递归
     *
     * @param context 上下文
     * @return 对象的活动对象，如果它不是活动对象，则为空。
     */
    public static Ability scanForActivity(Context context) {
        if (context == null) {
            return null;
        }
        if (context instanceof Ability) {
            return (Ability) context;
        }
        return null;
    }

    /**
     * 判断某Activity是否挂掉
     *
     * @param activity activity
     * @return return
     */
    public static boolean isActivityLiving(Ability activity) {
        if (activity == null) {
            return false;
        }
        if (activity.getLifecycle().getLifecycleState() == Lifecycle.Event.ON_STOP) {
            return false;
        }
        return true;
    }

    /**
     * 判断是否垂直方向
     *
     * @param context 上下文
     * @return true 垂直方向  false水平方向
     */
    public static boolean isVertical(Context context) {
        Configuration mConfiguration = context.getResourceManager().getConfiguration();
        boolean directionType = false;
        switch (mConfiguration.direction) {
            case Configuration.DIRECTION_HORIZONTAL: // 水平方向
                directionType = false;
                break;
            case Configuration.DIRECTION_VERTICAL: // 垂直方向
                directionType = true;
                break;
            default:
                break;
        }
        return directionType;
    }

    /**
     * 获取屏幕宽度
     *
     * @param context context
     * @return return
     */
    public static int getScreenWidth(Context context) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        return display.getAttributes().width;
    }

    /**
     * 获取屏幕高度
     *
     * @param context context
     * @return return
     */
    public static int getScreenHeight(Context context) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        return display.getAttributes().height;
    }

    /**
     * 获取状态栏高度
     *
     * @param context context
     * @return return
     */
    public static double getStatusBarHeight(Context context) {
        int statusBarHeight = 0;
        Point point1 = new Point();
        Point point2 = new Point();
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        display.getSize(point1);
        display.getRealSize(point2);
        statusBarHeight = (int) (point2.getPointY() - point1.getPointY());
        return statusBarHeight;
    }

    /**
     * 获取竖屏下状态栏高度
     *
     * @param context context
     * @return return
     */
    public static double getStatusBarHeightPortrait(Context context) {
        int statusBarHeight = 0;
        Point point1 = new Point();
        Point point2 = new Point();
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        display.getSize(point1);
        display.getRealSize(point2);
        statusBarHeight = (int) (point2.getPointY() - point1.getPointY());
        return statusBarHeight;
    }

    /**
     * 获取NavigationBar的高度
     *
     * @param context context
     * @return return
     */
    public static int getNavigationBarHeight(Context context) {
        return 0;
    }

    /**
     * 是否存在NavigationBar
     *
     * @param context context
     * @return return
     */
    public static boolean hasNavigationBar(Context context) {
        return false;
    }

    /**
     * 获取屏幕宽度
     *
     * @param context context
     * @param isIncludeNav isIncludeNav
     * @return return
     */
    public static int getScreenWidth(Context context, boolean isIncludeNav) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        if (isIncludeNav) {
            return display.getAttributes().width + getNavigationBarHeight(context);
        } else {
            return display.getAttributes().width;
        }
    }

    /**
     * 获取屏幕高度
     *
     * @param context context
     * @param isIncludeNav isIncludeNav
     * @return return
     */
    public static int getScreenHeight(Context context, boolean isIncludeNav) {
        Display display = DisplayManager.getInstance().getDefaultDisplay(context).get();
        if (isIncludeNav) {
            return display.getAttributes().height + getNavigationBarHeight(context);
        } else {
            return display.getAttributes().height;
        }
    }

    /**
     * 获取集合的快照
     *
     * @param other other
     * @param <T> t
     * @return return
     */
    public static <T> List<T> getSnapshot(Collection<T> other) {
        List<T> result = new ArrayList<>(other.size());
        for (T item : other) {
            if (item != null) {
                result.add(item);
            }
        }
        return result;
    }

    /**
     * 如果WindowManager还未创建，则创建一个新的WindowManager返回。否则返回当前已创建的WindowManager。
     *
     * @return return
     */
    public static WindowManager getWindowManager() {
        return WindowManager.getInstance();
    }

    /**
     * 边缘检测
     *
     * @param context context
     * @param event event
     * @return return
     */
    public static boolean isEdge(Context context, TouchEvent event) {
        int edgeSize = AttrHelper.vp2px(40, context);
        return event.getPointerScreenPosition(0).getX() < edgeSize
            || event.getPointerScreenPosition(0).getX() > getScreenWidth(context, true) - edgeSize
            || event.getPointerScreenPosition(0).getY() < edgeSize
            || event.getPointerScreenPosition(0).getY() > getScreenHeight(context, true) - edgeSize;
    }

    /**
     * 将毫秒数格式化为"##:##"的时间
     *
     * @param milliseconds 毫秒数
     * @return ##:##
     */
    public static String formatTime(long milliseconds) {
        if (milliseconds <= 0 || milliseconds >= 24 * COUNT_60 * COUNT_60 * COUNT_1000) {
            return "00:00";
        }
        long totalSeconds = milliseconds / COUNT_1000;
        long seconds = totalSeconds % COUNT_60;
        long minutes = (totalSeconds / COUNT_60) % COUNT_60;
        long hours = totalSeconds / COUNT_3600;
        StringBuilder stringBuilder = new StringBuilder();
        Formatter mFormatter = new Formatter(stringBuilder, Locale.getDefault());
        if (hours > 0) {
            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
        } else {
            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
        }
    }

    /**
     * 保存播放位置，以便下次播放时接着上次的位置继续播放.
     *
     * @param context 上下文
     * @param url 视频链接url
     * @param position position
     */
    public static synchronized void savePlayPosition(Context context, String url, long position) {
        if (context == null) {
            return;
        }
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        Preferences preferences = databaseHelper.getPreferences("VIDEO_PLAYER_PLAY_POSITION");
        preferences.putFloat(url, position);
        preferences.flush();
    }

    /**
     * 取出上次保存的播放位置
     *
     * @param context 上下文
     * @param url 视频链接url
     * @return 上次保存的播放位置
     */
    public static synchronized long getSavedPlayPosition(Context context, String url) {
        if (context == null) {
            return 0;
        }
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        Preferences preferences = databaseHelper.getPreferences("VIDEO_PLAYER_PLAY_POSITION");
        return (long) preferences.getFloat(url, 0);
    }

    /**
     * 清楚播放位置的痕迹
     *
     * @param context 上下文
     */
    public static synchronized void clearPlayPosition(Context context) {
        if (context == null) {
            return;
        }
        DatabaseHelper databaseHelper = new DatabaseHelper(context);
        Preferences preferences = databaseHelper.getPreferences("VIDEO_PLAYER_PLAY_POSITION");
        preferences.clear();
    }

    /**
     * 判断网络是否连接
     *
     * @param context context
     * @return return
     */
    public static boolean isConnected(Context context) {
        return NetManager.getInstance(context).hasDefaultNet();
    }

    /**
     * 获取当前系统时间
     *
     * @return return
     */
    public static String getCurrentSystemTime() {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm", Locale.getDefault());
        Date date = new Date();
        return simpleDateFormat.format(date);
    }

    /**
     * 获取活动网络信息
     * 需添加权限
     *
     * @param context context
     * @return NetworkInfo
     */
    private static NetHandle getActiveNetworkInfo(Context context) {
        NetManager manager = NetManager.getInstance(context);
        if (manager == null) {
            return null;
        }
        return manager.getAppNet();
    }

    /**
     * 空指针检测，不能为null，可以为""
     *
     * @param obj obj对象
     * @param message 消息
     * @param <T> 泛型
     * @return obj
     * @throws NullPointerException NullPointerException
     */
    public static <T> T requireNonNull(T obj, String message) {
        if (obj == null) {
            throw new NullPointerException(message);
        }
        return obj;
    }

    /**
     * 空指针检测，不能为null，也不能为""
     *
     * @param obj obj对象
     * @param message 消息
     * @return 字符串
     * @throws IllegalArgumentException IllegalArgumentException
     */
    public static String requireNonEmpty(String obj, String message) {
        if (TextUtils.isEmpty(obj)) {
            throw new IllegalArgumentException(message);
        }
        return obj;
    }

    /**
     * 将毫秒换成00:00:00
     *
     * @param time 毫秒
     * @return 时间字符串
     */
    public static String getCountTimeByLong(long time) {
        // 秒
        long totalTime = time / COUNT_1000;
        long hour = 0L; // 时
        long minute = 0L; // 分
        long second = 0L; // 秒
        if (COUNT_3600 <= totalTime) {
            hour = totalTime / COUNT_3600;
            totalTime = totalTime - COUNT_3600 * hour;
        }
        if (COUNT_60 <= totalTime) {
            minute = totalTime / COUNT_60;
            totalTime = totalTime - COUNT_60 * minute;
        }
        if (0 <= totalTime) {
            second = totalTime;
        }
        StringBuilder sb = new StringBuilder();
        if (hour < COUNT_10) {
            sb.append(STRING_0).append(hour).append(STRING_M);
        } else {
            sb.append(hour).append(STRING_M);
        }
        if (minute < COUNT_10) {
            sb.append(STRING_0).append(minute).append(STRING_M);
        } else {
            sb.append(minute).append(STRING_M);
        }
        if (second < COUNT_10) {
            sb.append(STRING_0).append(second);
        } else {
            sb.append(second);
        }
        return sb.toString();
    }

    /**
     * 将毫秒换成 00:00 或者 00，这个根据具体时间来计算
     *
     * @param time 毫秒
     * @return 时间字符串
     */
    public static String getCountTime(long time) {
        long totalTime = time / COUNT_1000; // 秒
        long hour = 0L; // 时
        long minute = 0L; // 分
        long second = 0L; // 秒
        if (COUNT_3600 <= totalTime) {
            hour = totalTime / COUNT_3600;
            totalTime = totalTime - COUNT_3600 * hour;
        }
        if (COUNT_60 <= totalTime) {
            minute = totalTime / COUNT_60;
            totalTime = totalTime - COUNT_60 * minute;
        }
        if (0 <= totalTime) {
            second = totalTime;
        }
        StringBuilder sb = new StringBuilder();
        if (hour > 0) {
            if (hour < COUNT_10) {
                sb.append(STRING_0).append(hour).append(STRING_M);
            } else {
                sb.append(hour).append(STRING_M);
            }
        }
        if (minute > 0) {
            if (minute < COUNT_10) {
                sb.append(STRING_0).append(minute).append(STRING_M);
            } else {
                sb.append(minute).append(STRING_M);
            }
        }
        if (second < COUNT_10) {
            sb.append(STRING_0).append(second);
        } else {
            sb.append(second);
        }
        return sb.toString();
    }

    /**
     * 获取当前的播放核心
     *
     * @return return
     */
    public static Object getCurrentPlayerFactory() {
        VideoPlayerConfig config = VideoViewManager.getConfig();
        Object playerFactory = null;
        try {
            Field mPlayerFactoryField = config.getClass().getDeclaredField("mPlayerFactory");
            mPlayerFactoryField.setAccessible(true);
            playerFactory = mPlayerFactoryField.get(config);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            VideoLogUtils.e(e.getMessage());
        }
        return playerFactory;
    }

    /**
     * 将View从父控件中移除
     *
     * @param component component
     */
    public static void removeViewFormParent(Component component) {
        if (component == null) {
            return;
        }
        ComponentContainer parent = (ComponentContainer) component.getComponentParent();
        if (parent instanceof StackLayout) {
            ((StackLayout) parent).removeComponent(component);
        }
    }

    /**
     * playState2str
     *
     * @param state state
     * @return return
     */
    public static String playState2str(int state) {
        String playStateString;
        switch (state) {
            case ConstantKeys.CurrentState.STATE_PREPARING:
                playStateString = "preparing";
                break;
            case ConstantKeys.CurrentState.STATE_PREPARED:
                playStateString = "prepared";
                break;
            case ConstantKeys.CurrentState.STATE_PLAYING:
                playStateString = "playing";
                break;
            case ConstantKeys.CurrentState.STATE_PAUSED:
                playStateString = "pause";
                break;
            case ConstantKeys.CurrentState.STATE_BUFFERING_PAUSED:
                playStateString = "buffering";
                break;
            case ConstantKeys.CurrentState.STATE_COMPLETED:
                playStateString = "buffered";
                break;
            case ConstantKeys.CurrentState.STATE_BUFFERING_PLAYING:
                playStateString = "playback completed";
                break;
            case ConstantKeys.CurrentState.STATE_ERROR:
                playStateString = "error";
                break;
            default:
            case ConstantKeys.CurrentState.STATE_IDLE:
                playStateString = "idle";
                break;
        }
        return String.format("playState: %s", playStateString);
    }

    /**
     * playerState2str
     *
     * @param state state
     * @return return
     */
    public static String playerState2str(int state) {
        String playerStateString;
        switch (state) {
            case ConstantKeys.PlayMode.MODE_FULL_SCREEN:
                playerStateString = "full screen";
                break;
            case ConstantKeys.PlayMode.MODE_TINY_WINDOW:
                playerStateString = "tiny screen";
                break;
            default:
            case ConstantKeys.PlayMode.MODE_NORMAL:
                playerStateString = "normal";
                break;
        }
        return String.format("playerState: %s", playerStateString);
    }

    /**
     * vp转像素
     *
     * @param context 上下文
     * @param vp vp值
     * @return px 像素值
     */
    public static int vp2px(Context context, float vp) {
        return DisplayManager.getInstance().getDefaultDisplay(context)
            .map(display -> (int) (display.getAttributes().densityPixels * vp))
            .orElse(0);
    }
}
